﻿using PredictionBuilder.Attributes;
using PredictionBuilder.Enum;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.NetworkInformation;
using System.Reflection;
using System.Text;

namespace PredictionBuilder.Model
{
    /// <summary>
    /// 条件构造模型类
    /// </summary>
    /// <typeparam name="T"></typeparam>
    public class BuilderModel<T> where T : class,new()
    {
        /// <summary>
        /// ctor
        /// </summary>
        public BuilderModel(object[] ignoreValues,params Type[] types)
        {
            if (!ignoreValues.Any())
            {
                IgnoreValues = new object[1] { null };
            }
            else
            {
                IgnoreValues = ignoreValues;
            }
            
            Types = types;
            PropertyBuildInfos = GetPropertyBuildInfos();
        }
        /// <summary>
        /// 泛型类型
        /// </summary>
        public Type ModelType
        {
            get
            {
                return typeof(T);
            }
        }
        /// <summary>
        /// 属性构建信息
        /// </summary>
        public List<PropertyBuildInfo> PropertyBuildInfos { get;}
        /// <summary>
        /// 生成表达式的泛型集合类型
        /// </summary>
        public Type[] Types { get;}
        /// <summary>
        /// 被忽略的值
        /// </summary>
        public object[] IgnoreValues { get;} = new object[2] { null, 0 };
        private List<PropertyBuildInfo> GetPropertyBuildInfos()
        {
            List<PropertyBuildInfo> buildInfos = new List<PropertyBuildInfo>();
            foreach(var prop in typeof(T).GetProperties())
            {
                PropertyBuildInfo buildInfo = new PropertyBuildInfo()
                {
                    ModelPropertyInfo = prop,
                    ParameterOrderAttribute = prop.GetCustomAttribute<ParameterOrderAttribute>() ?? new ParameterOrderAttribute(),
                    //ConditionAttribute= prop.GetCustomAttribute<ConditionAttribute>() ?? new ConditionAttribute(),
                    SkipBuildAttribute = prop.GetCustomAttribute<SkipBuildAttribute>() ?? new SkipBuildAttribute(false,null, IgnoreValues),
                    ConnectAttribute = prop.GetCustomAttribute<ConnectAttribute>() ?? new ConnectAttribute(),
                    OperatorAttribute=prop.GetCustomAttribute<OperatorAttribute>() ?? new OperatorAttribute(),
                    MappingTargetAttribute=prop.GetCustomAttribute<MappingTargetAttribute>() ?? new MappingTargetAttribute(),
                    CustomMethodAttribute=prop.GetCustomAttribute<CustomMethodAttribute>()
                };
                buildInfo.TargetType = GetMapType(buildInfo);
                buildInfos.Add(buildInfo);
            }
            return buildInfos;
        }
        private List<TargetTypeModel> GetMapType(PropertyBuildInfo propertyBuildInfo)
        {
            List<TargetTypeModel> list = new List<TargetTypeModel>();
            if (!propertyBuildInfo.MappingTargetAttribute.Values.Any())
            {
                foreach(Type type in Types)
                {
                    var prop= type.GetProperty(propertyBuildInfo.ModelPropertyInfo.Name);
                    if(prop != null)
                    {
                        TargetTypeModel targetTypeModel = new TargetTypeModel()
                        {
                            TargetType = type,
                            TargetPropertyName = propertyBuildInfo.ModelPropertyInfo.Name
                        };
                        list.Add(targetTypeModel);
                    }
                }
            }
            else
            {
                foreach(string targetName in propertyBuildInfo.MappingTargetAttribute.Values)
                {
                    string[] arr = targetName.Split('.');
                    Func<Type, bool> typeFunc = t => true;
                    string propName=string.Empty;
                    if (arr.Length == 1)
                    {
                        propName = arr[0];
                    }
                    else if(arr.Length == 2)
                    {
                        typeFunc = t => t.Name == arr[0];
                        propName = arr[1];
                    }
                    else
                    {
                        StringBuilder newKey = new StringBuilder();
                        for (int i = 0; i < arr.Length - 1; i++)
                        {
                            newKey.Append($"{arr[i]}.");
                        }
                        string typeName = newKey.ToString().TrimEnd('.');
                        propName = arr[arr.Length - 1];
                        typeFunc=t=>t.FullName== typeName;
                    }
                    foreach(Type type in Types.Where(typeFunc))
                    {
                        var prop=type.GetProperty(propName);
                        if(prop != null)
                        {
                            TargetTypeModel targetTypeModel = new TargetTypeModel()
                            {
                                TargetType = type,
                                TargetPropertyName = propName
                            };
                            list.Add(targetTypeModel);
                        }
                    }
                }
            }
            return list.Distinct().ToList();
        }


    }
    /// <summary>
    /// 属性绑定信息
    /// </summary>
    public class PropertyBuildInfo
    {
        /// <summary>
        /// 将作为哪个类型的属性
        /// </summary>
        public List<TargetTypeModel> TargetType { get; set; }
        /// <summary>
        /// 构建模型的属性
        /// </summary>
        public PropertyInfo ModelPropertyInfo { get; set; }
        /// <summary>
        /// 属性上的条件特性
        /// </summary>
        //public ConditionAttribute ConditionAttribute { get; set; }
        /// <summary>
        /// 忽略构建表达式的特性
        /// </summary>
        public SkipBuildAttribute SkipBuildAttribute { get; set; }
        /// <summary>
        /// 表达式操作符特性
        /// </summary>
        public OperatorAttribute OperatorAttribute { get; set; }
        /// <summary>
        /// 映射属性名特性
        /// </summary>
        public MappingTargetAttribute MappingTargetAttribute { get; set; }
        /// <summary>
        /// 条件连接特性
        /// </summary>
        public ConnectAttribute ConnectAttribute { get; set; }
        /// <summary>
        /// 自定义方法特性
        /// </summary>
        public CustomMethodAttribute CustomMethodAttribute { get; set; }

        /// <summary>
        /// 参数排序特性
        /// </summary>
        public ParameterOrderAttribute ParameterOrderAttribute { get; set; }
        /// <summary>
        /// 是否聚合条件 如果为聚合条件会跳过普通模式的生成
        /// </summary>
        public bool IsAggregate { get; set; } = false;
        /// <summary>
        /// 是否自定义运算符
        /// </summary>
        public bool IsCustom { get { return CustomMethodAttribute != null; } }
    }
    /// <summary>
    /// 映射类实体
    /// </summary>
    public class TargetTypeModel
    {
        /// <summary>
        /// 映射的类型
        /// </summary>
        public Type TargetType { get; set; }
        /// <summary>
        /// 映射的属性名
        /// </summary>
        public string TargetPropertyName { get; set; }
    }
    /// <summary>
    /// 聚合模型
    /// </summary>
    public class AggregateInfo
    {
        /// <summary>
        /// 属性绑定信息
        /// </summary>
        public List<PropertyBuildInfo> AggregatePropertyBuildInfo { get; set; } = new List<PropertyBuildInfo>();
        /// <summary>
        /// 内连接类型
        /// </summary>
        public ConnectType InnerJoinType { get; set; }
        /// <summary>
        /// 外连接类型
        /// </summary>
        public ConnectType OuterJoinType { get; set; }
    }
}
